package cn.iocoder.yudao.framework.datapermission.v2;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.biz.permission.PermissionCommonApi;
import cn.iocoder.yudao.framework.common.biz.permission.dto.DeptDataPermissionRespDTO;
import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  默认的数据权限范围提供者
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/04/06
 */
@Slf4j
public class DefaultDataPermissionScopeProvider implements DataPermissionScopeProvider {
    private static final List<String> USER_FIELD_NAMES = List.of("userId", "adminUserId");
    private static final List<String> DEPT_FIELD_NAMES = List.of("deptId", "departmentId");

    @Override
    public String getTitle() {
        return "基于用户及部门的数据权限范围提供者";
    }

    @Override
    public List<? extends Serializable> getScopeIds(String fieldName) {
        // 获取当前登录用户
        LoginUser currentUser = SecurityFrameworkUtils.getLoginUser();
        if (currentUser == null || currentUser.getId() <= 0) {
            log.warn("无法获取当前登录用户，以无数据权限处理：{}", currentUser);
            return List.of();
        }
        if (isDeptFieldName(fieldName)) {
            return buildDeptIds(currentUser);
        }
        if (isUserFieldName(fieldName)) {
            return buildUserIds(currentUser);
        }
        log.debug("数据权限范围提供者未能识别该字段类型(%s)，忽略数据权限处理！".formatted(fieldName));
        return null;
    }

    @Override
    public List<Class<?>> getEntityClasses() {
        return List.of();
    }

    /**
     * 未配置数据权限时的默认可见自己的
     */
    @Nullable
    protected List<? extends Serializable> buildUserIds(@Nonnull LoginUser currentUser) {
        List<Serializable> ids = new ArrayList<>(1);
        ids.add(currentUser.getId());
        return ids;
    }

    /**
     * 未配置数据权限时的默认本部门
     */
    @Nullable
    protected List<? extends Serializable> buildDeptIds(@Nonnull LoginUser currentUser) {
        // 获得部门数据权限
        DeptDataPermissionRespDTO deptDataPermissionRespDTO = currentUser.getContext(DeptDataPermissionRule.class.getSimpleName(), DeptDataPermissionRespDTO.class);
        // 从上下文中拿不到，则调用逻辑进行获取
        if (deptDataPermissionRespDTO == null) {
            deptDataPermissionRespDTO = SpringUtil.getBean(PermissionCommonApi.class).getDeptDataPermission(currentUser.getId());
            if (deptDataPermissionRespDTO == null) {
                String deptIdStr = MapUtil.get(currentUser.getInfo(), LoginUser.INFO_KEY_DEPT_ID, String.class);
                if (StrUtil.isBlank(deptIdStr)) {
                    // 未获取到部门编号，表示无部门数据权限
                    return List.of();
                }
                long deptId = NumberUtil.parseLong(deptIdStr);
                if (deptId <= 0) {
                    // 未获取到部门编号，表示无部门数据权限
                    return List.of();
                }
                // 有所属部门数据权限
                return List.of(deptId);
            }
            // 添加到上下文中，避免重复计算
            currentUser.setContext(DeptDataPermissionRule.class.getSimpleName(), deptDataPermissionRespDTO);
        }
        log.trace("[buildDeptIds][LoginUser({}) 获取部门数据权限为 {}]", JSONUtil.toJsonStr(currentUser), JSONUtil.toJsonStr(deptDataPermissionRespDTO));
        if (Boolean.TRUE.equals(deptDataPermissionRespDTO.getAll())) {
            // 有所有部门数据权限
            return null;
        }
        Set<Long> deptIds = deptDataPermissionRespDTO.getDeptIds();
        if (CollUtil.isEmpty(deptIds)) {
            // 无部门数据权限
            return List.of();
        }
        // 有指定部门数据权限
        return deptIds.stream().toList();
    }

    /**
     * 是否为可支持的用户字段
     */
    protected boolean isUserFieldName(String fieldName) {
        return USER_FIELD_NAMES.contains(fieldName);
    }

    /**
     * 是否为可支持的部门字段
     */
    protected boolean isDeptFieldName(String fieldName) {
        return DEPT_FIELD_NAMES.contains(fieldName);
    }

}
